package com.xlh.virtualization.dao.helper;

import com.google.common.collect.Lists;
import com.xlh.virtualization.constant.ContainerStatusEnum;
import com.xlh.virtualization.dao.ContainerMapper;
import com.xlh.virtualization.domain.Container;
import com.xlh.virtualization.domain.ContainerCondition;
import com.xlh.virtualization.domain.ContainerContext;
import com.xlh.virtualization.domain.example.ContainerExample;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import java.util.ArrayList;
import java.util.List;

import static com.xlh.virtualization.constant.ContainerRoleEnum.SLAVE;
import static com.xlh.virtualization.constant.ContainerStatusEnum.RUNNING;

/**
 * @author cheer
 */
@Repository
public class ContainerMapperHelper {

    @Autowired
    private ContainerMapper containerMapper;

    public void deleteById(Long id) {
        Container container = Container.builder()
                .id(id)
                .deleted(true)
                .build();
        containerMapper.updateByPrimaryKeySelective(container);
    }

    public void deleteByIds(List<Long> ids) {
        if (CollectionUtils.isNotEmpty(ids)) {
            ContainerExample example = new ContainerExample();
            example.or().andIdIn(ids).andDeletedEqualTo(false);
            Container container = Container.builder()
                    .deleted(true)
                    .build();
            containerMapper.updateByExampleSelective(container, example);
        }
    }

    public void trueDeleteByIds(List<Long> ids) {
        if (CollectionUtils.isNotEmpty(ids)) {
            ContainerExample example = new ContainerExample();
            example.or().andIdIn(ids).andDeletedEqualTo(false);
            containerMapper.deleteByExample(example);
        }
    }

    public void updateStatus(Long id, Integer status) {
        Container container = Container.builder()
                .id(id)
                .containerStatus(status)
                .build();
        containerMapper.updateByPrimaryKeySelective(container);
    }

    public void updateStatus(List<Long> ids, Integer status) {
        if (CollectionUtils.isNotEmpty(ids)) {
            ContainerExample example = new ContainerExample();
            example.or().andIdIn(ids)
                    .andDeletedEqualTo(false);
            Container container = Container.builder()
                    .containerStatus(status)
                    .build();
            containerMapper.updateByExampleSelective(container, example);
        }
    }

    public void updateStatus(Long userId, Integer contextType, Long contextId, Integer status) {
        ContainerExample example = new ContainerExample();
        example.or().andUserIdEqualTo(userId)
                .andContextTypeEqualTo(contextType)
                .andContextIdEqualTo(contextId)
                .andDeletedEqualTo(false);
        Container container = Container.builder()
                .containerStatus(status)
                .build();
        containerMapper.updateByExampleSelective(container, example);
    }

    public void updateResolution(List<Long> ids, Boolean fullScreen, Double length, Double width) {
        if (CollectionUtils.isNotEmpty(ids)) {
            ContainerExample example = new ContainerExample();
            example.or().andIdIn(ids)
                    .andDeletedEqualTo(false);
            Container container = Container.builder()
                    .fullScreen(fullScreen)
                    .length(String.valueOf(length))
                    .width(String.valueOf(width))
                    .build();
            containerMapper.updateByExampleSelective(container, example);
        }
    }

    public Container getContainerById(Long id) {
        Container container = containerMapper.selectByPrimaryKey(id);
        if (container == null || container.getDeleted()) {
            return null;
        }
        return container;
    }

    public Container getContainerByCondition(ContainerCondition condition) {
        ContainerExample example = new ContainerExample();
        ContainerExample.Criteria criteria = example.createCriteria();
        criteria.andUserIdEqualTo(condition.getUserId())
                .andContextTypeEqualTo(condition.getContextType())
                .andContextIdEqualTo(condition.getContextId())
                .andContainerRoleEqualTo(condition.getContainerRole().getCode())
                .andImageIdEqualTo(condition.getImage().getId())
                .andGpuEqualTo(condition.getGpu())
                .andDeletedEqualTo(false);
        if (SLAVE == condition.getContainerRole()) {
            criteria.andRoleNumberEqualTo(condition.getRoleNumber());
        }
        List<Container> containers = containerMapper.selectByExample(example);
        if (CollectionUtils.isNotEmpty(containers)) {
            return containers.get(0);
        }
        return null;

    }

    public List<Container> getContainerByContext(ContainerContext containerContext) {
        ContainerExample example = new ContainerExample();
        ContainerExample.Criteria criteria = example.createCriteria();
        criteria.andUserIdEqualTo(containerContext.getUserId())
                .andContextTypeEqualTo(containerContext.getContextType())
                .andContextIdEqualTo(containerContext.getContextId())
                .andDeletedEqualTo(false);
        example.setOrderByClause("container_role asc, role_number asc");
        return containerMapper.selectByExample(example);
    }

    public List<Container> listAllContainers() {
        ContainerExample example = new ContainerExample();
        example.or().andDeletedEqualTo(false);
        return containerMapper.selectByExample(example);
    }

    public List<Container> listContainers(List<Long> ids) {
        if (CollectionUtils.isEmpty(ids)) {
            return new ArrayList<>();
        }
        ContainerExample example = new ContainerExample();
        example.or().andIdIn(ids)
                .andDeletedEqualTo(false);
        return containerMapper.selectByExample(example);
    }

    public List<Container> listRunningContainers() {
        ContainerExample example = new ContainerExample();
        example.or().andContainerStatusEqualTo(RUNNING.getCode())
                .andDeletedEqualTo(false);
        return containerMapper.selectByExample(example);
    }

    public List<Container> listRunningContainers(Long userId, List<Integer> contextTypes) {
        if (userId == null || CollectionUtils.isEmpty(contextTypes)) {
            return new ArrayList<>();
        }
        ContainerExample example = new ContainerExample();
        example.or().andUserIdEqualTo(userId)
                .andContextTypeIn(contextTypes)
                .andContainerStatusEqualTo(RUNNING.getCode())
                .andDeletedEqualTo(false);
        return containerMapper.selectByExample(example);
    }

    public List<Container> listExitedContainers(List<Long> ids) {
        if (CollectionUtils.isEmpty(ids)) {
            return new ArrayList<>();
        }
        ContainerExample example = new ContainerExample();
        example.or().andIdIn(ids)
                .andContainerStatusIn(Lists.newArrayList(ContainerStatusEnum.EXITED.getCode(),
                        ContainerStatusEnum.STOPPING.getCode()))
                .andDeletedEqualTo(false);
        return containerMapper.selectByExample(example);
    }

    public List<Container> listContainersByContext(Long userId, Integer contextType, Long contextId) {
        ContainerExample example = new ContainerExample();
        example.or().andUserIdEqualTo(userId)
                .andContextTypeEqualTo(contextType)
                .andContextIdEqualTo(contextId)
                .andDeletedEqualTo(false);
        example.setOrderByClause("container_role asc, role_number asc");
        return containerMapper.selectByExample(example);
    }

    public List<Container> listContainersByContext(Integer contextType, Long contextId) {
        ContainerExample example = new ContainerExample();
        example.or().andContextTypeEqualTo(contextType)
                .andContextIdEqualTo(contextId)
                .andDeletedEqualTo(false);
        return containerMapper.selectByExample(example);
    }

    public List<Container> listContainersByContext(Integer contextType, List<Long> contextIds, List<Long> userIds) {
        ContainerExample example = new ContainerExample();
        ContainerExample.Criteria criteria = example.createCriteria();
        criteria.andContextTypeEqualTo(contextType)
                .andDeletedEqualTo(false);
        if (CollectionUtils.isNotEmpty(contextIds)) {
            criteria.andContextIdIn(contextIds);
        }
        if (CollectionUtils.isNotEmpty(userIds)) {
            criteria.andUserIdIn(userIds);
        }
        return containerMapper.selectByExample(example);
    }

    public List<Container> listExtraContainersByContext(Long userId, Integer contextType, Long contextId, List<Long> ids) {
        ContainerExample example = new ContainerExample();
        ContainerExample.Criteria criteria = example.createCriteria();
        criteria.andUserIdEqualTo(userId)
                .andContextTypeEqualTo(contextType)
                .andContextIdEqualTo(contextId)
                .andDeletedEqualTo(false);
        if (CollectionUtils.isNotEmpty(ids)) {
            criteria.andIdNotIn(ids);
        }
        return containerMapper.selectByExample(example);
    }

    public List<Container> listContainersByImageId(Long imageId) {
        ContainerExample example = new ContainerExample();
        example.or().andImageIdEqualTo(imageId)
                .andDeletedEqualTo(false);
        return containerMapper.selectByExample(example);
    }

    public List<Container> listContainersByImageIds(List<Long> imageIds) {
        if (CollectionUtils.isEmpty(imageIds)) {
            return new ArrayList<>();
        }
        ContainerExample example = new ContainerExample();
        example.or().andImageIdIn(imageIds)
                .andDeletedEqualTo(false);
        return containerMapper.selectByExample(example);
    }

}
